/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package tp_imag.model;

import ij.process.ByteProcessor;
import java.awt.image.BufferedImage;

/**
 * Proceso para ecualizar el histograma de una imagen
 *
 * @author gdenari
 */
public class EcualizadorImagen {

    final static private int CANT_NIVELES_GRIS = 256;

    /* vector resultante con los brillos que pasan a tener las imagenes ecualizadas
     que inicialmente tenian un brillo uk.
     Por ejemplo una imagen que antes tenia un brillo de nivel 4 en un pixel, ahora tendrá
     un brillo de nivel vk[4] en ese pixel */
    private int[] vk = new int[CANT_NIVELES_GRIS];

    /* vector con la cantidad de veces que aparece el brillo i en la imagen (histograma) */
    private long[] veces = new long[CANT_NIVELES_GRIS];

    /* vector con la probabilidad acumulada */
    private long[] Sk = new long[CANT_NIVELES_GRIS];

    /* Sk minimo */
    private long Skmin = 0;

    /* Sk maximo */
    private long Skmax = 0;
    
    /* the image */
    private ByteProcessor bpImage = null;

    public EcualizadorImagen(BufferedImage image) {
        bpImage = new ByteProcessor(image);
    }

    private void calculate() {

        Skmax = bpImage.getWidth() * bpImage.getHeight();

        /* calculamos el histograma inicial */
        for (int x = 0; x < bpImage.getWidth(); x++) {
            for (int y = 0; y < bpImage.getHeight(); y++) {
                int pixel = bpImage.getPixel(x, y);
                veces[pixel]++;
            }
        }

        Skmin = veces[0];

        long acumulado = 0;
        for(int k = 0; k < CANT_NIVELES_GRIS; k++) {
            acumulado += veces[k];
            vk[k] = Math.round(getV(acumulado));
        }

    }

    /* Formula para calcular el nuevo valor del pixel en funcion del
     acumulado en k */
    private float getV(long sk) {
        return (((CANT_NIVELES_GRIS - 1) * (sk - Skmin)) / (Skmax - Skmin));
    }

    public ByteProcessor equalizeImage() {

        /* Realizamos el calculo del vector Vk */
        calculate();

        /* Reemplazamos los pixeles de la imagen por los nuevos valores */
        for (int x = 0; x < bpImage.getWidth(); x++) {
            for (int y = 0; y < bpImage.getHeight(); y++) {
                int pixel = bpImage.getPixel(x, y);
                bpImage.set(x, y, vk[pixel]);                
            }
        }

        return bpImage;
    }
}
